package com.hgw.imsever.netty.handler;

import com.alibaba.fastjson.JSONObject;
import com.hgw.imsever.common.RedisKeyConsts;
import com.hgw.imsever.common.utils.RedisUtil;
import com.hgw.imsever.netty.ChannelGroupMap;
import com.hgw.imsever.netty.enums.ChatRoomType;
import com.hgw.imsever.netty.enums.MessageTypeEnum;
import com.hgw.imsever.netty.model.ConnectionMessage;
import com.hgw.imsever.netty.model.GroupChatChatMessageProtocol;
import com.hgw.imsever.netty.model.SingleChatChatMessageProtocol;
import com.hgw.imsever.netty.task.UserOfflineTask;
import com.hgw.imsever.netty.task.UserOnlineTask;
import com.hgw.imsever.service.UserGroupService;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
import io.netty.util.CharsetUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.stream.Collectors;

@Slf4j
public class BinaryWebSocketFrameHandler extends SimpleChannelInboundHandler<BinaryWebSocketFrame> {

    private RedisUtil redisUtil;
    private UserGroupService userGroupService;

    public BinaryWebSocketFrameHandler(RedisUtil redisUtil, UserGroupService userGroupService) {
        this.redisUtil = redisUtil;
        this.userGroupService = userGroupService;
    }

    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, BinaryWebSocketFrame binaryWebSocketFrame) throws Exception {
        ByteBuf content = binaryWebSocketFrame.content();
        if (content.readableBytes() > 0) {
            String contentStr = binaryWebSocketFrame.content().toString(CharsetUtil.UTF_8);
            JSONObject parseObject = JSONObject.parseObject(contentStr);
            //消息类型
            Integer messageType = parseObject.getInteger("messageType");

            //判断消息类型
            if (MessageTypeEnum.CONNECT.getCode() == messageType) {
                //连接建立成功
                ConnectionMessage connectionMessage = parseObject.toJavaObject(ConnectionMessage.class);
                ChannelGroupMap.channelMap.put(connectionMessage.getUserId(), channelHandlerContext.channel());
                String channelId = channelHandlerContext.channel().id().asLongText();
                //保存用户登录channel和在线状态
                channelHandlerContext.channel().eventLoop().submit(new UserOnlineTask(channelId, connectionMessage.getUserId(), redisUtil));
            } else if (MessageTypeEnum.CHAT.getCode() == messageType) {
                //聊天 类型
                String chatType = parseObject.getString("chatType");

                if (ChatRoomType.SINGLE.name().equalsIgnoreCase(chatType)) {
                    SingleChatChatMessageProtocol singleChatMessageProtocol = parseObject.toJavaObject(SingleChatChatMessageProtocol.class);
                    Channel channel = ChannelGroupMap.channelMap.get(singleChatMessageProtocol.getToId());
                    if (channel != null) {
                        channel.writeAndFlush(new BinaryWebSocketFrame(Unpooled.copiedBuffer(parseObject.toJSONString().getBytes(CharsetUtil.UTF_8))));
                    }
                } else if (ChatRoomType.GROUP.name().equalsIgnoreCase(chatType)) {
                    GroupChatChatMessageProtocol groupChatMessageProtocol = parseObject.toJavaObject(GroupChatChatMessageProtocol.class);
                    //获取该群组的所有在线用户id
                    List<String> userIds = userGroupService.queryAliveUsersByGroupId(groupChatMessageProtocol.getChatRoomId());
                    if (!CollectionUtils.isEmpty(userIds)) {
                        //不包含自己
                        userIds.remove(groupChatMessageProtocol.getFromId());
                        List<Channel> channelList = userIds.stream()
                                .map(i -> ChannelGroupMap.channelMap.get(i))
                                .filter(c -> c != null).collect(Collectors.toList());

                        if (!CollectionUtils.isEmpty(channelList)) {
                            channelList.stream().forEach(i -> {
                                if (i != channelHandlerContext.channel()) {
                                    i.writeAndFlush(new BinaryWebSocketFrame(Unpooled.copiedBuffer(parseObject.toJSONString().getBytes(CharsetUtil.UTF_8))));
                                }
                            });
                        }
                    }
                }

            } else if (MessageTypeEnum.SIGNED.getCode() == messageType) {
                //消息签收

            } else {
                log.error("UNKNOWN MessageType:{}", messageType);
            }
        }
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        String channelId = ctx.channel().id().asLongText();
        //todo 从Redis中取出通道Id和用户id对应数据
        String userId = redisUtil.hget(RedisKeyConsts.CHAT_CHANNEL_USER, channelId);
        //移除对应channel
        ChannelGroupMap.channelMap.remove(userId);
        ctx.channel().eventLoop().submit(new UserOfflineTask(channelId, userId, redisUtil));
        ctx.channel().close();
    }


}
